//===============================================================================
// Microsoft patterns & practices Enterprise Library Contribution
// Policy Injection Application Block
//===============================================================================

using System;
using System.Configuration;
using System.ComponentModel;
using System.Transactions;
using System.Windows.Forms;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.PolicyInjection.Configuration;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
using EntLibContrib.PolicyInjection.CallHandlers;

namespace EntLibContrib.PolicyInjection.CallHandlers.Configuration
{
	/// <summary>
	/// Transaction Scope Call Handler Data
	/// </summary>
	public class TransactionScopeCallHandlerData : CallHandlerData
	{
		#region Constants
		private const string TransactionScopeOptionPropertyName = "transactionScopeOption";
		private const string TimeoutPropertyName = "timeout";
		private const string IsolationLevelPropertyName = "isolationLevel";
		private const string EnterpriseServicesInteropOptionPropertyName = "interopOption";
		private const string CompletePropertyName = "complete";
		#endregion

		#region Properties
		/// <summary>
		/// Gets or Sets the Transaction Scope Option.
		/// </summary>
		/// <value>The "transactionScopeOption" attribute in configuration</value>
		[ConfigurationProperty(TransactionScopeOptionPropertyName, DefaultValue = "Required")]
		public TransactionScopeOption TransactionScopeOption
		{
			get { return (TransactionScopeOption)base[TransactionScopeOptionPropertyName]; }
			set { base[TransactionScopeOptionPropertyName] = value; }
		}

		/// <summary>
		/// Gets or Sets the Timeout.
		/// </summary>
		/// <value>The "timeout" attribute in configuration</value>
		[ConfigurationProperty(TimeoutPropertyName, DefaultValue = "00:01:00")]
		public TimeSpan Timeout
		{
			get { return (TimeSpan)base[TimeoutPropertyName]; }
			set { base[TimeoutPropertyName] = value; }
		}

		/// <summary>
		/// Gets or Sets the Isolation Level.
		/// </summary>
		/// <value>The "isolationLevel" attribute in configuration</value>
		[ConfigurationProperty(IsolationLevelPropertyName, DefaultValue = "Serializable")]
		public IsolationLevel IsolationLevel
		{
			get { return (IsolationLevel)base[IsolationLevelPropertyName]; }
			set { base[IsolationLevelPropertyName] = value; }
		}

		/// <summary>
		/// Gets or Sets the EnterpriseServicesInteropOption.
		/// </summary>
		/// <value>The "interopOption" attribute in configuration</value>
		[ConfigurationProperty(EnterpriseServicesInteropOptionPropertyName, DefaultValue = "None")]
		public EnterpriseServicesInteropOption InteropOption
		{
			get { return (EnterpriseServicesInteropOption)base[EnterpriseServicesInteropOptionPropertyName]; }
			set { base[EnterpriseServicesInteropOptionPropertyName] = value; }
		}

		/// <summary>
		/// Gets or Sets whether the TransactionScope will complete on success.
		/// </summary>
		/// <value>The "complete" attribute in configuration</value>
		[ConfigurationProperty(CompletePropertyName, DefaultValue = "true")]
		public bool Complete
		{
			get { return (bool)base[CompletePropertyName]; }
			set { base[CompletePropertyName] = value; }
		}
		#endregion

		#region Construction
		/// <summary>
		/// Construct a new <see cref="TransactionScopeCallHandlerData"/>.
		/// </summary>
		public TransactionScopeCallHandlerData()
		{
		}

		/// <summary>
		/// Construct a new <see cref="TransactionScopeCallHandlerData"/>.
		/// </summary>
		/// <param name="handlerName">Name of the handler.</param>

		public TransactionScopeCallHandlerData(string handlerName)
			: base(handlerName, typeof(TransactionScopeCallHandler))
		{
		}

		/// <summary>
		/// Construct a new <see cref="TransactionScopeCallHandlerData"/>.
		/// </summary>
		/// <param name="handlerName">Name of the handler.</param>
		/// <param name="handlerOrder">The handler order.</param>
		public TransactionScopeCallHandlerData(string handlerName, int handlerOrder)
			: base(handlerName, typeof(TransactionScopeCallHandler))
		{
			Order = handlerOrder;
		}
		#endregion

		#region Public Methods
		/// <summary>
		/// Adds the call handler represented by this configuration object to <paramref name="policy"/>.
		/// </summary>
		/// <param name="policy">The policy to which the rule must be added.</param>
		/// <param name="configurationSource">The configuration source from which additional information
		/// can be retrieved, if necessary.</param>
		public override void ConfigurePolicy(PolicyDefinition policy, IConfigurationSource configurationSource)
		{
			TransactionOptions transactionOptions = new TransactionOptions();
			transactionOptions.Timeout = Timeout;
			transactionOptions.IsolationLevel = IsolationLevel;

			policy.AddCallHandler<TransactionScopeCallHandler>(
					new ContainerControlledLifetimeManager(),
					new InjectionConstructor(
							new InjectionParameter<TransactionScopeOption>(this.TransactionScopeOption),
							new InjectionParameter<TransactionOptions>(transactionOptions),
							new InjectionParameter<EnterpriseServicesInteropOption>(this.InteropOption),
							new InjectionParameter<bool>(this.Complete),
							new InjectionParameter<int>(this.Order)));
		}
		#endregion
	}
}
